package it.okkam.importdatacreaterdf;

import it.okkam.costants.CodiciComuni;
import it.okkam.costants.Costanti;
import it.okkam.strutturedati.ConfineComune;
import it.okkam.strutturedati.ParticellaCatastale;
import it.okkam.strutturedati.Poligono;
import it.okkam.strutturedati.Punto;
import it.okkam.strutturedati.Vertice;
import it.okkam.utility.ApriStream;
import it.okkam.utility.CoordinateConversion;
import it.okkam.utility.S;
import it.okkam.utility.SGeo;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.StringTokenizer;

import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.RDF;

public class PseudoConfiniComune {
	public static void main(String[] args) {
		PseudoConfiniComune psudoConfiniComune = new PseudoConfiniComune();
		List<ConfineComune> lista = psudoConfiniComune.leggiConfiniComune("/home/okkam/Nicola/Dati catastali completi/pseudo_comuni.txt");//"Users/inserisciquiiltuonomeutente/Desktop/coordinate comuni.rtfd"
		psudoConfiniComune.creaFileRDF("ciao", lista, "TURTLE");
	}
	
	public List<ConfineComune> leggiConfiniComune(String fileConfiniPath) {

		ArrayList<ConfineComune> listaConfiniComuni = new ArrayList<ConfineComune>();
		ArrayList<String> contenutoFileConfini = null;
		ApriStream apriStream = new ApriStream();
		contenutoFileConfini = apriStream.apriStream(fileConfiniPath); // lettura file Confini

		listaConfiniComuni = creaListaConfiniComuni(contenutoFileConfini);
		return listaConfiniComuni;

	}
	
	private ArrayList<ConfineComune> creaListaConfiniComuni(ArrayList<String> contenutoFileConfini) {
		// TODO Auto-generated method stub
		ArrayList<ConfineComune> listaComuni = null;
		String comune = null;
		String codiceComune = null;
		int indiceOrdine = 0;
		Poligono poligonoLetto = null;
		Set<Vertice> puntiPoligono = null;
		listaComuni = new ArrayList<ConfineComune>();
		
		for (String rigaLetta : contenutoFileConfini) {
			if (rigaLetta.equalsIgnoreCase("END")) { // caso fine comune
				poligonoLetto = new Poligono();
				poligonoLetto.setPoligono(puntiPoligono); // carico i punti del poligono

				// creo la particella e la popolo
				ConfineComune confineLetto = new ConfineComune();
				confineLetto.setPoligono(poligonoLetto);
				confineLetto.setComune(comune);
				codiceComune = CodiciComuni.ComuneMap2Code.get(comune);
				confineLetto.setCodiceComune(codiceComune);

				// carico la particella sulla lista delle particelle lette
				listaComuni.add(confineLetto);
				// mi preparo a leggere un'altra particella
				indiceOrdine = 0;
			}
			if (rigaLetta.startsWith("0")){// da ampliare//caso vertice
				Vertice vertice = new Vertice();
				indiceOrdine++;
				vertice = leggiVertice(rigaLetta, indiceOrdine);
				puntiPoligono.add(vertice);

			}
			else{ // caso nome comune
				comune = rigaLetta;
				puntiPoligono = new HashSet<Vertice>();
			}
			}
		return listaComuni;
		}
	
	
	
	
	
	
	// METODI PUBBLICI

	public double convertiTestoToNumero(String coordinataTestuale) {
		double coordinata = 0;
		int potenza;
		String radice, segno, potenzaStringa;
		if (coordinataTestuale != null) {
			// estraggo la radice della coordinata
			int indice = coordinataTestuale.indexOf('E');
			radice = coordinataTestuale.substring(0, indice);
			coordinata = Double.parseDouble(radice);
			// estraggo il segno della potenza
			segno = coordinataTestuale.substring((indice + 1), (indice + 2));
			// estraggo l'esponente
			potenzaStringa = coordinataTestuale.substring(indice + 2);
			potenza = Integer.parseInt(potenzaStringa);

			// adegue l'esponente al segno
			if (segno.equals("-"))
				potenza = potenza * (-1);
			// calcolo la coordinata
			coordinata = coordinata * (Math.pow(10, potenza));

			return coordinata;
		} else
			return 0.0;
	}

	// METODI PRIVATI

	private Vertice leggiVertice(String lettura, int indice) {
		Vertice vertex = new Vertice();
		Punto puntoLetto = new Punto();

		StringTokenizer st = new StringTokenizer(lettura, " ");
		while (st.hasMoreTokens()) {
			String coordX = st.nextToken();
			String coordY = st.nextToken();
			double cX = convertiTestoToNumero(coordX);
			double cY = convertiTestoToNumero(coordY);
			double lat = utm2Lat(cX, cY, "32 T "/* NORD_ITALIA */);
			double lon = utm2Lon(cX, cY, "32 T "/* NORD_ITALIA */);
			puntoLetto.setX(lat);
			puntoLetto.setY(lon);
			// System.out.println(lat + " " + lon);
			vertex.setVertice(puntoLetto);
			vertex.setCardinalita(indice);
		}

		return vertex;
	}
	private double utm2Lat(Double utmLat, Double utmLon, String zona) {

		CoordinateConversion converter = new CoordinateConversion();

		String utmLatStr = Double.toString(utmLat);
		String utmLonStr = Double.toString(utmLon);
		String utmCoordinates = zona + utmLatStr + " " + utmLonStr;

		double[] latLon = converter.utm2LatLon(utmCoordinates);

		double lat = latLon[0];
		return lat;

	}

	private double utm2Lon(Double utmLat, Double utmLon, String zona) {

		CoordinateConversion converter = new CoordinateConversion();

		String utmLatStr = Double.toString(utmLat);
		String utmLonStr = Double.toString(utmLon);
		String utmCoordinates = zona + utmLatStr + " " + utmLonStr;

		double[] latLon = converter.utm2LatLon(utmCoordinates);
		double longitudine = latLon[1];

		return longitudine;
	}

	private String creaURIParticella(String ontologia,String numEDen , ParticellaCatastale particella){
		String URIParticella = null;
		if (particella.getEdificialeFondiaria().equalsIgnoreCase("edificiale")){
			//text here caso EDIFICIALE
			URIParticella = ontologia + "/" + "pe" + "/" + numEDen ;
		}
		else{
			//text here caso Fondiaria
			URIParticella = ontologia + "/" + "pf" + "/" + numEDen;
		}
		
		return URIParticella;
	}
	
	private String getNumEDen (ParticellaCatastale particella){
		String numEDen = particella.getNumero();
		if (particella.getDenominatore()!= null){
			numEDen = numEDen + "/" + particella.getDenominatore();
		}
		
		return numEDen;
	}

	private String creaURIPoligono(String ontologia, ConfineComune confine){
		String URIpoligono = null; 
		
		ontologia = ontologia + "/poligono/";
		URIpoligono = ontologia + confine.getComune(); 
		
		return URIpoligono;
	}
	


	
	private String creaURIPunto(String ontologia, Punto punto){
		String URIpunto = null; 
		ontologia = ontologia + "/punto";
		
		URIpunto = ontologia + "/lat/" + getParteIntera(punto.getX()) + "/" + getParteFrazionaria(punto.getX()) + "/lon/" + getParteIntera(punto.getY()) + "/" +getParteFrazionaria(punto.getY()) + "/wgs84"; 
		
		return URIpunto;
	}
	
	private String creaURIVertice (String URIpoligono , String URIpunto , String URIontologia , String ordine ){
		String URIvertice = URIpoligono;
		int indice = URIontologia.length();
		String subURI = URIpunto.substring(indice);
		URIvertice = URIvertice + subURI + "/w/" + ordine;		
		return URIvertice;
		
	}
	private String getParteIntera (double numero){
		String intera=null;
		String numeroStr = Double.toString(numero);
		int punto = trovaPosizionePunto(numeroStr);
		intera = numeroStr.substring(0,punto);
		return intera;
	}
	
	private String getParteFrazionaria (double numero){
		String fraz=null;
		String numeroStr = Double.toString(numero);
		int punto = trovaPosizionePunto(numeroStr);
		fraz = numeroStr.substring(punto+1);
		return fraz;
	}
	
	private int trovaPosizionePunto (String stringaIndagata){
		int i= 0;
		for (int j=0; j < stringaIndagata.length() ; j++  ){
			if (stringaIndagata.charAt(j)=='.'){
				i=j;
			}
		}
		return i;
		
	}


public File creaFileRDF(String nomeFile, List<ConfineComune> lista, String serializzazione) {
	// TODO Auto-generated method stub
	File fileConfiniRdf = new File("/home/okkam/Nicola/Dati catastali completi/confiniComuni.rdf");
	Model model = ModelFactory.createDefaultModel();
	model.setNsPrefix("pc", "http://www.okkam.it/ont/particella_catastale.owl#"); // set del prefisso
	String ontologiaConfini = "http://www.okkam.it/ont/particella_catastale.owl#";
	Costanti.setUriComuni();
	Costanti.setCodiceComune();
	
	for(ConfineComune confine:lista){
		String comuneURI = null;
		String poligonoURI = null;
		String puntoURI = null;
		String verticeURI = null;
		String codiceComune = null;
		
		// creazione risorsa comune con uri dell ENS privato
		comuneURI = Costanti.uriComuni.get(confine.getComune());
		Resource comuneRisorsa = model.createResource(comuneURI);
		codiceComune = Costanti.codiceComune.get(confine.getComune());
		comuneRisorsa.addProperty(S.haCodiceComuneCatastale, codiceComune);
		
		// creazione risorsa poligono
		poligonoURI = creaURIPoligono(ontologiaConfini, confine);
		Resource poligonoRisorsa = model.createResource(poligonoURI);
		comuneRisorsa.addProperty(S.haPoligono, poligonoRisorsa);
		
		Poligono poligonoLetto = confine.getPoligono();
		Set<Vertice> listaVertici = poligonoLetto.getPoligono();
		
		for (Vertice verticeLetto: listaVertici){
			int ordine = verticeLetto.getCardinalita();
			
			Punto puntoLetto = verticeLetto.getVertice();
			puntoURI = creaURIPunto(ontologiaConfini, puntoLetto);
			verticeURI = creaURIVertice(poligonoURI, puntoURI, ontologiaConfini, Integer.toString(ordine));
			Resource verticeRisorsa = model.createResource(verticeURI);	
			Resource puntoRisorsa = model.createResource(puntoURI);
			double x = puntoLetto.getX();
			double y = puntoLetto.getY();
			puntoRisorsa.addProperty(SGeo.lat,  Double.toString(x));
			puntoRisorsa.addProperty(SGeo.long_,  Double.toString(y));	
			verticeRisorsa.addProperty(S.haPunto, puntoRisorsa);
			verticeRisorsa.addProperty(S.haNumeroOrdine, Integer.toString(ordine));
			poligonoRisorsa.addProperty(S.haVertice, verticeURI);
		}
	}
	
	try{
	model.write(new PrintWriter(fileConfiniRdf), serializzazione);
	}
	catch(FileNotFoundException e) {			
		e.printStackTrace();
	}
	System.out.println("Creazione file " + fileConfiniRdf.getName() +" terminata!");
	return fileConfiniRdf;
}
}